home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / diagnose.cpp < prev    next >
C/C++ Source or Header  |  1999-10-15  |  97KB  |  2,494 lines

  1. // $Id: diagnose.cpp,v 1.12 1999/10/15 02:30:39 shields Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <assert.h>
  12. #include <iostream.h>
  13. #include "diagnose.h"
  14. #include "control.h"
  15. #include "semantic.h"
  16. #include "case.h"
  17. #include "spell.h"
  18.  
  19. void DiagnoseParser::ReallocateStacks()
  20. {
  21.     int old_stack_length = stack_length;
  22.  
  23.     stack_length += STACK_INCREMENT;
  24.  
  25.     assert(stack_length <= SHRT_MAX);
  26.  
  27.     int *old_stack = stack;
  28.     stack = (int *) memmove(new int[stack_length], stack, old_stack_length * sizeof(int));
  29.     delete [] old_stack;
  30.  
  31.     Location *old_location_stack = location_stack;
  32.     location_stack = (Location *) memmove(new Location[stack_length], location_stack, old_stack_length * sizeof(Location));
  33.     delete [] old_location_stack;
  34.  
  35.     Ast **old_parse_stack = parse_stack;
  36.     parse_stack = (Ast **) memmove(new Ast *[stack_length], parse_stack, old_stack_length * sizeof(Ast *));
  37.     delete [] old_parse_stack;
  38.  
  39.     int *old_temp_stack = temp_stack;
  40.     temp_stack = (int *) memmove(new int[stack_length], temp_stack, old_stack_length * sizeof(int));
  41.     delete [] old_temp_stack;
  42.  
  43.     int *old_next_stack = next_stack;
  44.     next_stack = (int *) memmove(new int[stack_length], next_stack, old_stack_length * sizeof(int));
  45.     delete [] old_next_stack;
  46.  
  47.     int *old_prev_stack = prev_stack;
  48.     prev_stack = (int *) memmove(new int[stack_length], prev_stack, old_stack_length * sizeof(int));
  49.     delete [] old_prev_stack;
  50.  
  51.     int *old_scope_index = scope_index;
  52.     scope_index = (int *) memmove(new int[stack_length], scope_index, old_stack_length * sizeof(int));
  53.     delete [] old_scope_index;
  54.  
  55.     int *old_scope_position = scope_position;
  56.     scope_position = (int *) memmove(new int[stack_length], scope_position, old_stack_length * sizeof(int));
  57.     delete [] old_scope_position;
  58.  
  59.     return;
  60. }
  61.  
  62.  
  63. void DiagnoseParser::DiagnoseParse()
  64. {
  65.     lex_stream -> Reset();
  66.  
  67.     TokenObject curtok = lex_stream -> Gettoken();
  68.  
  69.     int prev_pos,
  70.         pos,
  71.         next_pos,
  72.         i,
  73.         tok,
  74.         lhs_symbol,
  75.         act = START_STATE;
  76.  
  77.     ReallocateStacks();
  78.  
  79. /*****************************************************************/
  80. /* Start parsing.                                                */
  81. /*****************************************************************/
  82.     state_stack_top = 0;
  83.     stack[state_stack_top] = act;
  84.  
  85.     tok = lex_stream -> Kind(curtok);
  86.     location_stack[state_stack_top] = Loc(curtok);
  87.  
  88.     //
  89.     // Process a terminal
  90.     //
  91.     do
  92.     {
  93.         /*************************************************************/
  94.         /* Synchronize state stacks and update the location stack.   */
  95.         /*************************************************************/
  96.         prev_pos = -1;
  97.         prev_stack_top = -1;
  98.  
  99.         next_pos = -1;
  100.         next_stack_top = -1;
  101.  
  102.         pos = state_stack_top;
  103.         temp_stack_top = state_stack_top - 1;
  104.         for (i = 0; i <= state_stack_top; i++)
  105.             temp_stack[i] = stack[i];
  106.  
  107.         act = t_action(act, tok, lex_stream);
  108. /*****************************************************************/
  109. /* When a reduce action is encountered, we compute all REDUCE    */
  110. /* and associated goto actions induced by the current token.     */
  111. /* Eventually, a SHIFT, SHIFT-REDUCE, ACCEPT or ERROR action is  */
  112. /* computed...                                                   */
  113. /*****************************************************************/
  114.         while (act <= NUM_RULES)
  115.         {
  116.             do
  117.             {
  118.                 temp_stack_top -= (rhs[act]-1);
  119.                 //
  120.                 // if no error detected?
  121.                 //     semantic_action(act);
  122.                 //
  123.                 act = nt_action(temp_stack[temp_stack_top], lhs[act]);
  124.             } while(act <= NUM_RULES);
  125.             /*************************************************/
  126.             /* ... Update the maximum useful position of the */
  127.             /* (STATE_)STACK, push goto state into stack, and*/
  128.             /* compute next action on current symbol ...     */
  129.             /*************************************************/
  130.             if (temp_stack_top + 1 >= stack_length)
  131.                 ReallocateStacks();
  132.             pos = Min(pos, temp_stack_top);
  133.             temp_stack[temp_stack_top + 1] = act;
  134.             act = t_action(act, tok, lex_stream);
  135.         }
  136.  
  137. /*****************************************************************/
  138. /* At this point, we have a shift, shift-reduce, accept or error */
  139. /* action.  STACK contains the configuration of the state stack  */
  140. /* prior to executing any action on curtok. next_stack contains  */
  141. /* the configuration of the state stack after executing all      */
  142. /* reduce actions induced by curtok.  The variable pos indicates */
  143. /* the highest position in STACK that is still useful after the  */
  144. /* reductions are executed.                                      */
  145. /*****************************************************************/
  146.         while(act > ERROR_ACTION ||       /* SHIFT-REDUCE action */
  147.               act < ACCEPT_ACTION)               /* SHIFT action */
  148.         {
  149.             next_stack_top = temp_stack_top + 1;
  150.             for (i = next_pos + 1; i <= next_stack_top; i++)
  151.                 next_stack[i] = temp_stack[i];
  152.  
  153.             for (i = pos + 1; i <= next_stack_top; i++)
  154.                 location_stack[i] = location_stack[state_stack_top];
  155.  
  156.             /*****************************************************/
  157.             /* If we have a shift-reduce, process it as well as  */
  158.             /* the goto-reduce actions that follow it.           */
  159.             /*****************************************************/
  160.             if (act > ERROR_ACTION)
  161.             {
  162.                 act -= ERROR_ACTION;
  163.                 do
  164.                 {
  165.                     next_stack_top -= (rhs[act]-1);
  166.                     //
  167.                     // if no error detected?
  168.                     //     semantic_action(act);
  169.                     //
  170.                     act = nt_action(next_stack[next_stack_top], lhs[act]);
  171.                 } while(act <= NUM_RULES);
  172.                 pos = Min(pos, next_stack_top);
  173.             }
  174.  
  175.             if (next_stack_top + 1 >= stack_length)
  176.                 ReallocateStacks();
  177.  
  178.             temp_stack_top = next_stack_top;
  179.             next_stack[++next_stack_top] = act;
  180.             next_pos = next_stack_top;
  181.  
  182.             /********************************************************/
  183.             /* Simulate the parser through the next token without   */
  184.             /* destroying STACK or next_stack.                      */
  185.             /********************************************************/
  186.             curtok = lex_stream -> Gettoken();
  187.             tok = lex_stream -> Kind(curtok);
  188.             act = t_action(act, tok, lex_stream);
  189.             while(act <= NUM_RULES)
  190.             {
  191.                 /*************************************************/
  192.                 /* ... Process all goto-reduce actions following */
  193.                 /* reduction, until a goto action is computed ...*/
  194.                 /*************************************************/
  195.                 do
  196.                 {
  197.                     lhs_symbol = lhs[act];
  198.                     temp_stack_top -= (rhs[act]-1);
  199.                     //
  200.                     // if no error detected?
  201.                     //     semantic_action(act);
  202.                     //
  203.                     act = (temp_stack_top > next_pos
  204.                                ? temp_stack[temp_stack_top]
  205.                                : next_stack[temp_stack_top]);
  206.                     act = nt_action(act, lhs_symbol);
  207.                 }   while(act <= NUM_RULES);
  208.  
  209.                 /*************************************************/
  210.                 /* ... Update the maximum useful position of the */
  211.                 /* (STATE_)STACK, push GOTO state into stack, and*/
  212.                 /* compute next action on current symbol ...     */
  213.                 /*************************************************/
  214.                 if (temp_stack_top + 1 >= stack_length)
  215.                     ReallocateStacks();
  216.  
  217.                 next_pos = Min(next_pos, temp_stack_top);
  218.                 temp_stack[temp_stack_top + 1] = act;
  219.                 act = t_action(act, tok, lex_stream);
  220.             }
  221.  
  222.             /*****************************************************/
  223.             /* No error was detected, Read next token into       */
  224.             /* PREVTOK element, advance CURTOK pointer and       */
  225.             /* update stacks.                                    */
  226.             /*****************************************************/
  227.             if (act != ERROR_ACTION)
  228.             {
  229.                 prev_stack_top = state_stack_top;
  230.                 for (i = prev_pos + 1; i <= prev_stack_top; i++)
  231.                     prev_stack[i] = stack[i];
  232.                 prev_pos = pos;
  233.  
  234.                 state_stack_top = next_stack_top;
  235.                 for (i = pos + 1; i <= state_stack_top; i++)
  236.                     stack[i] = next_stack[i];
  237.                 location_stack[state_stack_top] = Loc(curtok);
  238.                 pos = next_pos;
  239.             }
  240.         }
  241.  
  242.         /*********************************************************/
  243.         /* At this stage, either we have an ACCEPT or an ERROR   */
  244.         /* action.                                               */
  245.         /*********************************************************/
  246.         if (act == ERROR_ACTION)
  247.         {
  248.             //
  249.             // An error was detected.
  250.             //
  251.  
  252.             RepairCandidate candidate = ErrorRecovery(curtok);
  253.  
  254.             act = stack[state_stack_top];
  255.  
  256. /*****************************************************************/
  257. /* If the recovery was successful on a nonterminal candidate,    */
  258. /* parse through that candidate and "read" the next token.       */
  259. /*****************************************************************/
  260.             if (!candidate.symbol)
  261.                 break;
  262.             else if (candidate.symbol > NT_OFFSET)
  263.             {
  264.                 lhs_symbol = candidate.symbol - NT_OFFSET;
  265.                 act = nt_action(act, lhs_symbol);
  266.                 while(act <= NUM_RULES)
  267.                 {
  268.                     state_stack_top -= (rhs[act]-1);
  269.                     act = nt_action(stack[state_stack_top], lhs[act]);
  270.                 }
  271.                 stack[++state_stack_top] = act;
  272.                 curtok = lex_stream -> Gettoken();
  273.                 tok = lex_stream -> Kind(curtok);
  274.                 location_stack[state_stack_top] = Loc(curtok);
  275.             }
  276.             else
  277.             {
  278.                 tok = candidate.symbol;
  279.                 location_stack[state_stack_top] = candidate.location;
  280.             }
  281.         }
  282.     } while (act != ACCEPT_ACTION);
  283.  
  284.     error.PrintMessages();
  285.  
  286.     return;
  287. }
  288.  
  289.  
  290. /*****************************************************************/
  291. /*  This routine is invoked when an error is encountered.  It    */
  292. /* tries to diagnose the error and recover from it.  If it is    */
  293. /* successful, the state stack, the current token and the buffer */
  294. /* are readjusted; i.e., after a successful recovery,            */
  295. /* state_stack_top points to the location in the state stack     */
  296. /* that contains the state on which to recover; curtok           */
  297. /* identifies the symbol on which to recover.                    */
  298. /*                                                               */
  299. /* Up to three configurations may be available when this routine */
  300. /* is invoked. PREV_STACK may contain the sequence of states     */
  301. /* preceding any action on prevtok, STACK always contains the    */
  302. /* sequence of states preceding any action on curtok, and        */
  303. /* NEXT_STACK may contain the sequence of states preceding any   */
  304. /* action on the successor of curtok.                            */
  305. /*****************************************************************/
  306. RepairCandidate DiagnoseParser::ErrorRecovery(TokenObject error_token)
  307. {
  308.     TokenObject prevtok = lex_stream -> Previous(error_token);
  309.  
  310.     RepairCandidate candidate;
  311.  
  312. /*****************************************************************/
  313. /* Try primary phase recoveries. If not successful, try secondary*/
  314. /* phase recoveries.  If not successful and we are at end of the */
  315. /* file, we issue the end-of-file error and quit. Otherwise, ... */
  316. /*****************************************************************/
  317.     candidate = PrimaryPhase(error_token);
  318.     if (candidate.symbol)
  319.         return candidate;
  320.  
  321.     candidate = SecondaryPhase(error_token);
  322.     if (candidate.symbol)
  323.         return candidate;
  324.  
  325.     if (lex_stream -> Kind(error_token) == EOFT_SYMBOL)
  326.     {
  327.         error.Report(0, EOF_CODE, terminal_index[EOFT_SYMBOL],
  328.                                   Loc(prevtok), prevtok);
  329.         candidate.symbol = 0;
  330.         candidate.location = Loc(error_token);
  331.         return candidate;
  332.     }
  333.  
  334. /*****************************************************************/
  335. /* At this point, primary and (initial attempt at) secondary     */
  336. /* recovery did not work.  We will now get into "panic mode" and */
  337. /* keep trying secondary phase recoveries until we either find   */
  338. /* a successful recovery or have consumed the remaining input    */
  339. /* tokens.                                                       */
  340. /*****************************************************************/
  341.     while(lex_stream -> Kind(buffer[BUFF_UBOUND]) != EOFT_SYMBOL)
  342.     {
  343.         candidate = SecondaryPhase(buffer[MAX_DISTANCE - MIN_DISTANCE + 2]);
  344.         if (candidate.symbol)
  345.             return candidate;
  346.     }
  347.  
  348. /*****************************************************************/
  349. /* We reached the end of the file while panicking. Delete all    */
  350. /* remaining tokens in the input.                                */
  351. /*****************************************************************/
  352.     int i;
  353.     for (i = BUFF_UBOUND; lex_stream -> Kind(buffer[i]) == EOFT_SYMBOL; i--)
  354.         ;
  355.  
  356.     error.Report(0, DELETION_CODE, terminal_index[lex_stream -> Kind(prevtok)],
  357.                                    Loc(error_token), buffer[i]);
  358.  
  359.     candidate.symbol = 0;
  360.     candidate.location = Loc(buffer[i]);
  361.  
  362.     return candidate;
  363. }
  364.  
  365.  
  366. /*****************************************************************/
  367. /* This function tries primary and scope recovery on each        */
  368. /* available configuration.  If a successful recovery is found   */
  369. /* and no secondary phase recovery can do better, a diagnosis is */
  370. /* issued, the configuration is updated and the function returns */
  371. /* "true".  Otherwise, it returns "false".                       */
  372. /*****************************************************************/
  373. RepairCandidate DiagnoseParser::PrimaryPhase(TokenObject error_token)
  374. {
  375.     PrimaryRepairInfo repair,
  376.                       new_repair;
  377.  
  378.     RepairCandidate candidate;
  379.  
  380.     repair.distance = 0;
  381.     repair.misspell_index = 0;
  382.     repair.code = 0;
  383.  
  384.     candidate.symbol = 0;
  385.  
  386. /*****************************************************************/
  387. /* Initialize the buffer.                                        */
  388. /*****************************************************************/
  389.     int i = (next_stack_top >= 0 ? 3 : 2);
  390.     buffer[i] = error_token;
  391.  
  392.     int k;
  393.     for (k = i; k > 0; k--)
  394.         buffer[k - 1] = lex_stream -> Previous(buffer[k]);
  395.  
  396.     for (k = i + 1; k < BUFF_SIZE; k++)
  397.         buffer[k] = lex_stream -> Next(buffer[k - 1]);
  398.  
  399. /*****************************************************************/
  400. /* If NEXT_STACK_TOP > 0 then the parse was successful on CURTOK */
  401. /* and the error was detected on the successor of CURTOK. In     */
  402. /* that case, first check whether or not primary recovery is     */
  403. /* possible on next_stack ...                                    */
  404. /*****************************************************************/
  405.     if (next_stack_top >= 0)
  406.     {
  407.         repair.buffer_position = 3;
  408.         repair = CheckPrimaryDistance(next_stack, next_stack_top, repair);
  409.     }
  410.  
  411. /*****************************************************************/
  412. /* ... Next, try primary recovery on the current token...        */
  413. /*****************************************************************/
  414.     new_repair = repair;
  415.  
  416.     new_repair.buffer_position = 2;
  417.     new_repair = CheckPrimaryDistance(stack, state_stack_top, new_repair);
  418.     if (new_repair.distance > repair.distance ||
  419.         new_repair.misspell_index > repair.misspell_index)
  420.         repair = new_repair;
  421.  
  422. /*****************************************************************/
  423. /* Finally, if prev_stack_top >= 0 then try primary recovery on  */
  424. /* the prev_stack configuration.                                 */
  425. /*****************************************************************/
  426.     if (prev_stack_top >= 0)
  427.     {
  428.         new_repair = repair;
  429.         new_repair.buffer_position = 1;
  430.         new_repair = CheckPrimaryDistance(prev_stack,
  431.                                           prev_stack_top, new_repair);
  432.         if (new_repair.distance > repair.distance ||
  433.             new_repair.misspell_index > repair.misspell_index)
  434.             repair = new_repair;
  435.     }
  436.  
  437. /*****************************************************************/
  438. /* Before accepting the best primary phase recovery obtained,    */
  439. /* ensure that we cannot do better with a similar secondary      */
  440. /* phase recovery.                                               */
  441. /*****************************************************************/
  442.     if (next_stack_top >= 0)             /* next_stack available */
  443.     {
  444.         if (SecondaryCheck(next_stack,next_stack_top,3,repair.distance))
  445.               return candidate;
  446.     }
  447.     else if (SecondaryCheck(stack, state_stack_top, 2, repair.distance))
  448.              return candidate;
  449.  
  450. /*****************************************************************/
  451. /* First, adjust distance if the recovery is on the error token; */
  452. /* it is important that the adjustment be made here and not at   */
  453. /* each primary trial to prevent the distance tests from being   */
  454. /* biased in favor of deferred recoveries which have access to   */
  455. /* more input tokens...                                          */
  456. /*****************************************************************/
  457.     repair.distance = repair.distance - repair.buffer_position + 1;
  458.  
  459. /*****************************************************************/
  460. /* ...Next, adjust the distance if the recovery is a deletion or */
  461. /* (some form of) substitution...                                */
  462. /*****************************************************************/
  463.     if (repair.code == INVALID_CODE      ||
  464.         repair.code == DELETION_CODE     ||
  465.         repair.code == SUBSTITUTION_CODE ||
  466.         repair.code == MERGE_CODE)
  467.          repair.distance--;
  468.  
  469. /*****************************************************************/
  470. /* ... After adjustment, check if the most successful primary    */
  471. /* recovery can be applied.  If not, continue with more radical  */
  472. /* recoveries...                                                 */
  473. /*****************************************************************/
  474.     if (repair.distance < MIN_DISTANCE)
  475.         return candidate;
  476.  
  477. /*****************************************************************/
  478. /* When processing an insertion error, if the token preceeding   */
  479. /* the error token is not available, we change the repair code   */
  480. /* into a BEFORE_CODE to instruct the reporting routine that it  */
  481. /* indicates that the repair symbol should be inserted before    */
  482. /* the error token.                                              */
  483. /*****************************************************************/
  484.     if (repair.code == INSERTION_CODE)
  485.     {
  486.         if (! lex_stream -> Kind(buffer[repair.buffer_position - 1]))
  487.             repair.code = BEFORE_CODE;
  488.     }
  489.  
  490. /*****************************************************************/
  491. /* Select the proper sequence of states on which to recover,     */
  492. /* update stack accordingly and call diagnostic routine.         */
  493. /*****************************************************************/
  494.     if (repair.buffer_position == 1)
  495.     {
  496.         state_stack_top = prev_stack_top;
  497.         for (i = 0; i <= state_stack_top; i++)
  498.             stack[i] = prev_stack[i];
  499.     }
  500.     else if (next_stack_top >= 0 && repair.buffer_position >= 3)
  501.     {
  502.         state_stack_top = next_stack_top;
  503.         for (i = 0; i <= state_stack_top; i++)
  504.             stack[i] = next_stack[i];
  505.         location_stack[state_stack_top] = Loc(buffer[3]);
  506.     }
  507.  
  508.     return PrimaryDiagnosis(repair);
  509. }
  510.  
  511.  
  512. /*****************************************************************/
  513. /*     This function checks whether or not a given state has a   */
  514. /* candidate, whose string representaion is a merging of the two */
  515. /* tokens at positions buffer_position and buffer_position+1 in  */
  516. /* the buffer.  If so, it returns the candidate in question;     */
  517. /* otherwise it returns 0.                                       */
  518. /*****************************************************************/
  519. bool DiagnoseParser::MergeCandidate(int state, int buffer_position)
  520. {
  521.     int i,
  522.         k,
  523.         len,
  524.         len1,
  525.         len2;
  526.  
  527.     const wchar_t *p1,
  528.                   *p2;
  529.  
  530.     wchar_t str[MAX_TERM_LENGTH + 1];
  531.  
  532.     len1 = 0;
  533.     for (p1 = lex_stream -> NameString(buffer[buffer_position]); *p1; p1++)
  534.         len1++;
  535.     len2 = 0;
  536.     for (p2 = lex_stream -> NameString(buffer[buffer_position + 1]); *p2; p2++)
  537.         len2++;
  538.     len  = len1 + len2;
  539.  
  540.     p1 = lex_stream -> NameString(buffer[buffer_position]);
  541.     p2 = lex_stream -> NameString(buffer[buffer_position + 1]);
  542.  
  543.     if (len <= MAX_TERM_LENGTH)
  544.     {
  545.         wchar_t *p0;
  546.  
  547.         p0 = &str[0];
  548.         for (i = 0; i < len1; i++)
  549.             *(p0++) = p1[i];
  550.         for (i = 0; i < len2; i++)
  551.             *(p0++) = p2[i];
  552.         *p0 = U_NULL;
  553.  
  554.         for (i = asi(state); asr[i] != 0; i++)
  555.         {
  556.             k = terminal_index[asr[i]];
  557.             if (len == name_length[k])
  558.             {
  559.                 const char *p3 = &string_buffer[name_start[k]];
  560.  
  561.                 p0 = &str[0];
  562.                 while (*p0 != U_NULL)
  563.                 {
  564.                     wchar_t c = *(p3++);
  565.  
  566.                     if (Case::ToAsciiLower(*p0) != Case::ToAsciiLower(c))
  567.                         break;
  568.                     p0++;
  569.                 }
  570.                 if (*p0 == U_NULL)
  571.                     return asr[i];
  572.             }
  573.         }
  574.     }
  575.  
  576.     return 0;
  577. }
  578.  
  579.  
  580. /*****************************************************************/
  581. /* This procedure takes as arguments a parsing configuration     */
  582. /* consisting of a state stack (stack and stack_top) and a fixed */
  583. /* number of input tokens (starting at buffer_position) in the   */
  584. /* input BUFFER; and some reference arguments: repair_code,      */
  585. /* distance, misspell_index, candidate, and stack_position       */
  586. /* which it sets based on the best possible recovery that it     */
  587. /* finds in the given configuration.  The effectiveness of a     */
  588. /* a repair is judged based on two criteria:                     */
  589. /*                                                               */
  590. /*   1) the number of tokens that can be parsed after the repair */
  591. /*      is applied: distance.                                    */
  592. /*   2) how close to perfection is the candidate that is chosen: */
  593. /*      misspell_index.                                          */
  594. /* When this procedure is entered, distance, misspell_index and  */
  595. /* repair_code are assumed to be initialized.                    */
  596. /*****************************************************************/
  597. PrimaryRepairInfo DiagnoseParser::CheckPrimaryDistance
  598.        (int stck[], int stack_top, PrimaryRepairInfo repair)
  599. {
  600.     PrimaryRepairInfo scope_repair;
  601.     int i,
  602.         j,
  603.         k,
  604.         next_state,
  605.         max_pos,
  606.         act,
  607.         root,
  608.         symbol,
  609.         tok;
  610.  
  611. /*****************************************************************/
  612. /*  First, try scope and manual recovery.                        */
  613. /*****************************************************************/
  614. #if defined(SCOPE_REPAIR)
  615.     scope_repair = ScopeTrial(stck, stack_top, repair);
  616.     if (scope_repair.distance > repair.distance)
  617.         repair = scope_repair;
  618. #endif
  619.  
  620. /*****************************************************************/
  621. /*  Next, try merging the error token with its successor.        */
  622. /*****************************************************************/
  623.     symbol = MergeCandidate(stck[stack_top], repair.buffer_position);
  624.     if (symbol != 0)
  625.     {
  626.         j = ParseCheck(stck, stack_top,
  627.                        symbol, repair.buffer_position+2);
  628.         if ((j > repair.distance) ||
  629.             (j == repair.distance && repair.misspell_index < 10))
  630.         {
  631.             repair.misspell_index = 10;
  632.             repair.symbol = symbol;
  633.             repair.distance = j;
  634.             repair.code = MERGE_CODE;
  635.         }
  636.     }
  637.  
  638. /*****************************************************************/
  639. /* Next, try deletion of the error token.                        */
  640. /*****************************************************************/
  641.     j = ParseCheck(stck, stack_top,
  642.                    lex_stream -> Kind(buffer[repair.buffer_position+1]),
  643.                    repair.buffer_position+2);
  644.     if (lex_stream -> Kind(buffer[repair.buffer_position]) == EOLT_SYMBOL &&
  645.         lex_stream -> AfterEol(buffer[repair.buffer_position+1]))
  646.          k = 10;
  647.     else k = 0;
  648.     if (j > repair.distance || (j == repair.distance && k > repair.misspell_index))
  649.     {
  650.         repair.misspell_index = k;
  651.         repair.code = DELETION_CODE;
  652.         repair.distance = j;
  653.     }
  654.  
  655. /*****************************************************************/
  656. /* Update the error configuration by simulating all reduce and   */
  657. /* goto actions induced by the error token. Then assign the top  */
  658. /* most state of the new configuration to next_state.            */
  659. /*****************************************************************/
  660.     next_state = stck[stack_top];
  661.     max_pos = stack_top;
  662.     temp_stack_top = stack_top - 1;
  663.  
  664.     tok = lex_stream -> Kind(buffer[repair.buffer_position]);
  665.     lex_stream -> Reset(buffer[repair.buffer_position + 1]);
  666.     act = t_action(next_state, tok, lex_stream);
  667.     while(act <= NUM_RULES)
  668.     {
  669.         do
  670.         {
  671.             temp_stack_top -= (rhs[act]-1);
  672.             symbol = lhs[act];
  673.             act = (temp_stack_top > max_pos
  674.                                   ? temp_stack[temp_stack_top]
  675.                                   : stck[temp_stack_top]);
  676.             act = nt_action(act, symbol);
  677.         }   while(act <= NUM_RULES);
  678.         max_pos = Min(max_pos, temp_stack_top);
  679.         temp_stack[temp_stack_top + 1] = act;
  680.         next_state = act;
  681.         act = t_action(next_state, tok, lex_stream);
  682.     }
  683.  
  684. /*****************************************************************/
  685. /*  Next, place the list of candidates in proper order.          */
  686. /*****************************************************************/
  687.     root = 0;
  688.     for (i = asi(next_state); asr[i] != 0; i++)
  689.     {
  690.         symbol = asr[i];
  691.         if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL)
  692.         {
  693.             if (root == 0)
  694.                 list[symbol] = symbol;
  695.             else
  696.             {
  697.                 list[symbol] = list[root];
  698.                 list[root] = symbol;
  699.             }
  700.             root = symbol;
  701.         }
  702.     }
  703.  
  704.     if (stck[stack_top] != next_state)
  705.     {
  706.         for (i = asi(stck[stack_top]); asr[i] != 0; i++)
  707.         {
  708.             symbol = asr[i];
  709.             if (symbol != EOFT_SYMBOL && symbol != ERROR_SYMBOL &&
  710.                                          list[symbol] == 0)
  711.             {
  712.                 if (root == 0)
  713.                     list[symbol] = symbol;
  714.                 else
  715.                 {
  716.                     list[symbol] = list[root];
  717.                     list[root] = symbol;
  718.                 }
  719.                 root = symbol;
  720.             }
  721.         }
  722.     }
  723.  
  724.     i = list[root];
  725.     list[root] = 0;
  726.     root = i;
  727.  
  728. /*****************************************************************/
  729. /*  Next, try insertion for each possible candidate available in */
  730. /* the current state, except EOFT and ERROR_SYMBOL.              */
  731. /*****************************************************************/
  732.     symbol = root;
  733.     while(symbol != 0)
  734.     {
  735.         if (symbol == EOLT_SYMBOL &&
  736.             lex_stream -> AfterEol(buffer[repair.buffer_position]))
  737.              k = 10;
  738.         else k = 0;
  739.         j = ParseCheck(stck, stack_top,
  740.                        symbol, repair.buffer_position);
  741.         if (j > repair.distance)
  742.         {
  743.             repair.misspell_index = k;
  744.             repair.distance = j;
  745.             repair.symbol = symbol;
  746.             repair.code = INSERTION_CODE;
  747.         }
  748.         else if (j == repair.distance && k > repair.misspell_index)
  749.         {
  750.             repair.misspell_index = k;
  751.             repair.distance = j;
  752.             repair.symbol = symbol;
  753.             repair.code = INSERTION_CODE;
  754.         }
  755.  
  756.         symbol = list[symbol];
  757.     }
  758.  
  759. /*****************************************************************/
  760. /*  Next, Try substitution for each possible candidate available */
  761. /* in the current state, except EOFT and ERROR_SYMBOL.           */
  762. /*****************************************************************/
  763.     symbol = root;
  764.     while(symbol != 0)
  765.     {
  766.         if (symbol == EOLT_SYMBOL &&
  767.             lex_stream -> AfterEol(buffer[repair.buffer_position+1]))
  768.              k = 10;
  769.         else k = Misspell(symbol, buffer[repair.buffer_position]);
  770.         j = ParseCheck(stck, stack_top,
  771.                        symbol, repair.buffer_position+1);
  772.         if (j > repair.distance)
  773.         {
  774.             repair.misspell_index = k;
  775.             repair.distance = j;
  776.             repair.symbol = symbol;
  777.             repair.code = SUBSTITUTION_CODE;
  778.         }
  779.         else if (j == repair.distance && k > repair.misspell_index)
  780.         {
  781.             repair.misspell_index = k;
  782.             repair.symbol = symbol;
  783.             repair.code = SUBSTITUTION_CODE;
  784.         }
  785.         i = symbol;
  786.         symbol = list[symbol];
  787.         list[i] = 0;                             /* reset element */
  788.     }
  789.  
  790.  
  791. /*****************************************************************/
  792. /* Next, we try to insert a nonterminal candidate in front of the*/
  793. /* error token, or substituting a nonterminal candidate for the  */
  794. /* error token. Precedence is given to insertion.                */
  795. /*****************************************************************/
  796.      for (i = nasi(stck[stack_top]); nasr[i] != 0; i++)
  797.      {
  798.          symbol = nasr[i] + NT_OFFSET;
  799.          j = ParseCheck(stck, stack_top,
  800.                         symbol, repair.buffer_position+1);
  801.          if (j > repair.distance)
  802.          {
  803.              repair.misspell_index = 0;
  804.              repair.distance = j;
  805.              repair.symbol = symbol;
  806.              repair.code = INVALID_CODE;
  807.          }
  808.  
  809.          j = ParseCheck(stck, stack_top, symbol, repair.buffer_position);
  810.          if ((j > repair.distance) ||
  811.              (j == repair.distance && repair.code == INVALID_CODE))
  812.          {
  813.              repair.misspell_index = 0;
  814.              repair.distance = j;
  815.              repair.symbol = symbol;
  816.              repair.code = INSERTION_CODE;
  817.          }
  818.      }
  819.  
  820.     return repair;
  821. }
  822.  
  823.  
  824. /*****************************************************************/
  825. /* This procedure is invoked to issue a diagnostic message and   */
  826. /* adjust the input buffer.  The recovery in question is either  */
  827. /* the insertion of one or more scopes, the merging of the error */
  828. /* token with its successor, the deletion of the error token,    */
  829. /* the insertion of a single token in front of the error token   */
  830. /* or the substitution of another token for the error token.     */
  831. /*****************************************************************/
  832. RepairCandidate DiagnoseParser::PrimaryDiagnosis(PrimaryRepairInfo repair)
  833. {
  834.     RepairCandidate candidate;
  835.  
  836.     int name_index;
  837.  
  838. /*****************************************************************/
  839. /*  Issue diagnostic.                                            */
  840. /*****************************************************************/
  841.     TokenObject prevtok = buffer[repair.buffer_position - 1],
  842.                 curtok  = buffer[repair.buffer_position];
  843.  
  844.     switch(repair.code)
  845.     {
  846.         case INSERTION_CODE: case BEFORE_CODE:
  847.         {
  848.             if (repair.symbol > NT_OFFSET)
  849.                  name_index = GetNtermIndex(stack[state_stack_top],
  850.                                             repair.symbol,
  851.                                             repair.buffer_position);
  852.             else name_index = GetTermIndex(stack,
  853.                                            state_stack_top,
  854.                                            repair.symbol,
  855.                                            repair.buffer_position);
  856. //
  857. //            TokenObject t = curtok;
  858. //            if (repair.code == INSERTION_CODE)
  859. //            {
  860. //                if (repair.symbol != EOLT_SYMBOL && lex_stream -> AfterEol(curtok))
  861. //                     repair.code = BEFORE_CODE;
  862. //                else t = prevtok;
  863. //            }
  864. //
  865. //            error.report(0, repair.code, name_index, Loc(t), t);
  866. //
  867.             TokenObject t = (repair.code == INSERTION_CODE ? prevtok : curtok);
  868.             error.Report(0, repair.code, name_index, Loc(t), t);
  869.             break;
  870.         }
  871.         case INVALID_CODE:
  872.         {
  873.             name_index = GetNtermIndex(stack[state_stack_top],
  874.                                        repair.symbol,
  875.                                        repair.buffer_position + 1);
  876.             error.Report(0, repair.code, name_index, Loc(curtok), curtok);
  877.             break;
  878.         }
  879.         case SUBSTITUTION_CODE:
  880.         {
  881.             if (repair.misspell_index >= 6)
  882.                 name_index = terminal_index[repair.symbol];
  883.             else
  884.             {
  885.                 name_index = GetTermIndex(stack, state_stack_top,
  886.                                           repair.symbol,
  887.                                           repair.buffer_position + 1);
  888.                 if (name_index != terminal_index[repair.symbol])
  889.                     repair.code = INVALID_CODE;
  890.             }
  891.             error.Report(0, repair.code, name_index, Loc(curtok), curtok);
  892.             break;
  893.         }
  894.         case MERGE_CODE:
  895.         {
  896.             error.Report(0, repair.code, terminal_index[repair.symbol],
  897.                                          Loc(curtok), lex_stream -> Next(curtok));
  898.             break;
  899.         }
  900. #if defined(SCOPE_REPAIR)
  901.         case SCOPE_CODE:
  902.         {
  903.             for (int i = 0; i < scope_stack_top; i++)
  904.             {
  905.                 error.Report(0, repair.code,
  906.                                 -scope_index[i],
  907.                                 location_stack[scope_position[i]],
  908.                                 prevtok,
  909.                                 non_terminal_index[scope_lhs[scope_index[i]]]);
  910.             }
  911.  
  912.             repair.symbol = scope_lhs[scope_index[scope_stack_top]] + NT_OFFSET;
  913.             state_stack_top = scope_position[scope_stack_top];
  914.             error.Report(0, repair.code,
  915.                             -scope_index[scope_stack_top],
  916.                             location_stack[scope_position[scope_stack_top]],
  917.                             prevtok,
  918.                             GetNtermIndex(stack[state_stack_top],
  919.                                           repair.symbol,
  920.                                           repair.buffer_position)
  921.                            );
  922.             break;
  923.         }
  924. #endif
  925.         default: /* deletion */
  926.         {
  927.             error.Report(0, repair.code, terminal_index[ERROR_SYMBOL],
  928.                                          Loc(curtok), curtok);
  929.         }
  930.     }
  931.  
  932. /*****************************************************************/
  933. /*  Update buffer.                                               */
  934. /*****************************************************************/
  935.     switch (repair.code)
  936.     {
  937.         case INSERTION_CODE: case BEFORE_CODE:
  938. #if defined(SCOPE_REPAIR)
  939.         case SCOPE_CODE:
  940. #endif
  941.         {
  942.             candidate.symbol = repair.symbol;
  943.             candidate.location = Loc(buffer[repair.buffer_position]);
  944.             lex_stream -> Reset(buffer[repair.buffer_position]);
  945.  
  946.             break;
  947.         }
  948.  
  949.         case INVALID_CODE: case SUBSTITUTION_CODE:
  950.         {
  951.             candidate.symbol = repair.symbol;
  952.             candidate.location = Loc(buffer[repair.buffer_position]);
  953.             lex_stream -> Reset(buffer[repair.buffer_position + 1]);
  954.  
  955.             break;
  956.         }
  957.  
  958.         case MERGE_CODE:
  959.         {
  960.             candidate.symbol = repair.symbol;
  961.             candidate.location = Loc(buffer[repair.buffer_position]);
  962.             lex_stream -> Reset(buffer[repair.buffer_position + 2]);
  963.  
  964.             break;
  965.         }
  966.  
  967.         default: /* deletion */
  968.         {
  969.             candidate.location = Loc(buffer[repair.buffer_position + 1]);
  970.             candidate.symbol =
  971.                       lex_stream -> Kind(buffer[repair.buffer_position + 1]);
  972.             lex_stream -> Reset(buffer[repair.buffer_position + 2]);
  973.  
  974.             break;
  975.         }
  976.     }
  977.  
  978.     return candidate;
  979. }
  980.  
  981.  
  982. /*****************************************************************/
  983. /* This function takes as parameter an integer STACK_TOP that    */
  984. /* points to a STACK element containing the state on which a     */
  985. /* primary recovery will be made; the terminal candidate on which*/
  986. /* to recover; and an integer: buffer_position, which points to  */
  987. /* the position of the next input token in the BUFFER.  The      */
  988. /* parser is simulated until a shift (or shift-reduce) action    */
  989. /* is computed on the candidate.  Then we proceed to compute the */
  990. /* the name index of the highest level nonterminal that can      */
  991. /* directly or indirectly produce the candidate.                 */
  992. /*****************************************************************/
  993. int DiagnoseParser::GetTermIndex(int stck[], int stack_top,
  994.                                  int tok, int buffer_position)
  995. {
  996. /*****************************************************************/
  997. /* Initialize stack index of temp_stack and initialize maximum   */
  998. /* position of state stack that is still useful.                 */
  999. /*****************************************************************/
  1000.     int act = stck[stack_top],
  1001.         max_pos = stack_top,
  1002.         highest_symbol = tok;
  1003.  
  1004.     temp_stack_top = stack_top - 1;
  1005.  
  1006. /*****************************************************************/
  1007. /* Compute all reduce and associated actions induced by the      */
  1008. /* candidate until a SHIFT or SHIFT-REDUCE is computed. ERROR    */
  1009. /* and ACCEPT actions cannot be computed on the candidate in     */
  1010. /* this context, since we know that it is suitable for recovery. */
  1011. /*****************************************************************/
  1012.     lex_stream -> Reset(buffer[buffer_position]);
  1013.     act = t_action(act, tok, lex_stream);
  1014.     while(act <= NUM_RULES)
  1015.     {
  1016.         /*********************************************************/
  1017.         /* Process all goto-reduce actions following reduction,  */
  1018.         /* until a goto action is computed ...                   */
  1019.         /*********************************************************/
  1020.         do
  1021.         {
  1022.             temp_stack_top -= (rhs[act]-1);
  1023.             int lhs_symbol = lhs[act];
  1024.             act = (temp_stack_top > max_pos
  1025.                                   ? temp_stack[temp_stack_top]
  1026.                                   : stck[temp_stack_top]);
  1027.             act = nt_action(act, lhs_symbol);
  1028.         } while(act <= NUM_RULES);
  1029.         /*********************************************************/
  1030.         /* Compute new maximum useful position of (STATE_)stack, */
  1031.         /* push goto state into the stack, and compute next      */
  1032.         /* action on candidate ...                               */
  1033.         /*********************************************************/
  1034.         max_pos = Min(max_pos, temp_stack_top);
  1035.         temp_stack[temp_stack_top + 1] = act;
  1036.         act = t_action(act, tok, lex_stream);
  1037.     }
  1038.  
  1039. /********************************************************************/
  1040. /* At this stage, we have simulated all actions induced by the      */
  1041. /* candidate and we are ready to shift or shift-reduce it. First,   */
  1042. /* set tok and next_ptr appropriately and identify the candidate    */
  1043. /* as the initial highest_symbol. If a shift action was computed    */
  1044. /* on the candidate, update the stack and compute the next          */
  1045. /* action. Next, simulate all actions possible on the next input    */
  1046. /* token until we either have to shift it or are about to reduce    */
  1047. /* below the initial starting point in the stack (indicated by      */
  1048. /* max_pos as computed in the previous loop).  At that point,       */
  1049. /* return the highest_symbol computed.                              */
  1050. /********************************************************************/
  1051.     temp_stack_top++;   /* adjust top of stack to reflect last goto */
  1052.                         /* next move is shift or shift-reduce.      */
  1053.     int threshold = temp_stack_top;
  1054.  
  1055.     tok = lex_stream -> Kind(buffer[buffer_position]);
  1056.     lex_stream -> Reset(buffer[buffer_position + 1]);
  1057.  
  1058.     if (act > ERROR_ACTION)   /* shift-reduce on candidate? */
  1059.         act -= ERROR_ACTION;
  1060.     else                      /* shift on candidate ! */
  1061.     {
  1062.         temp_stack[temp_stack_top + 1] = act;
  1063.         act = t_action(act, tok, lex_stream);
  1064.     }
  1065.  
  1066.     while(act <= NUM_RULES)
  1067.     {
  1068.         /*********************************************************/
  1069.         /* Process all goto-reduce actions following reduction,  */
  1070.         /* until a goto action is computed ...                   */
  1071.         /*********************************************************/
  1072.         do
  1073.         {
  1074.             temp_stack_top -= (rhs[act]-1);
  1075.  
  1076.             if (temp_stack_top < threshold)
  1077.                 goto quit;
  1078.  
  1079.             int lhs_symbol = lhs[act];
  1080.             if (temp_stack_top == threshold)
  1081.                 highest_symbol = lhs_symbol + NT_OFFSET;
  1082.             act = (temp_stack_top > max_pos
  1083.                                   ? temp_stack[temp_stack_top]
  1084.                                   : stck[temp_stack_top]);
  1085.             act = nt_action(act, lhs_symbol);
  1086.         } while(act <= NUM_RULES);
  1087.  
  1088.         temp_stack[temp_stack_top + 1] = act;
  1089.         act = t_action(act, tok, lex_stream);
  1090.     }
  1091.  
  1092.  quit:
  1093.     return (highest_symbol > NT_OFFSET
  1094.                            ? non_terminal_index[highest_symbol - NT_OFFSET]
  1095.                            : terminal_index[highest_symbol]);
  1096. }
  1097.  
  1098. /*****************************************************************/
  1099. /* This function takes as parameter a starting state number:     */
  1100. /* start, a nonterminal symbol, A (candidate), and an integer,   */
  1101. /* buffer_position,  which points to the position of the next    */
  1102. /* input token in the BUFFER.                                    */
  1103. /* It returns the highest level non-terminal B such that         */
  1104. /* B =>*rm A.  I.e., there does not exists a nonterminal C such  */
  1105. /* that C =>+rm B. (Recall that for an LALR(k) grammar if        */
  1106. /* C =>+rm B, it cannot be the case that B =>+rm C)              */
  1107. /*****************************************************************/
  1108. int DiagnoseParser::GetNtermIndex(int start, int sym, int buffer_position)
  1109. {
  1110.     int act,
  1111.         tok,
  1112.         highest_symbol;
  1113.  
  1114.     highest_symbol = sym - NT_OFFSET;
  1115.  
  1116.     tok = lex_stream -> Kind(buffer[buffer_position]);
  1117.     lex_stream -> Reset(buffer[buffer_position + 1]);
  1118.  
  1119. /*****************************************************************/
  1120. /* Initialize stack index of temp_stack and initialize maximum   */
  1121. /* position of state stack that is still useful.                 */
  1122. /*****************************************************************/
  1123.     temp_stack_top = 0;
  1124.     temp_stack[temp_stack_top] = start;
  1125.  
  1126.     act = nt_action(start, highest_symbol);
  1127.     if (act > NUM_RULES) /* goto action? */
  1128.     {
  1129.         temp_stack[temp_stack_top + 1] = act;
  1130.         act = t_action(act, tok, lex_stream);
  1131.     }
  1132.  
  1133.     while(act <= NUM_RULES)
  1134.     {
  1135.         /*********************************************************/
  1136.         /* Process all goto-reduce actions following reduction,  */
  1137.         /* until a goto action is computed ...                   */
  1138.         /*********************************************************/
  1139.         do
  1140.         {
  1141.             temp_stack_top -= (rhs[act]-1);
  1142.             if (temp_stack_top < 0)
  1143.                 return non_terminal_index[highest_symbol];
  1144.             if (temp_stack_top == 0)
  1145.                 highest_symbol = lhs[act];
  1146.             act = nt_action(temp_stack[temp_stack_top], lhs[act]);
  1147.         } while(act <= NUM_RULES);
  1148.         temp_stack[temp_stack_top + 1] = act;
  1149.         act = t_action(act, tok, lex_stream);
  1150.     }
  1151.  
  1152.     return non_terminal_index[highest_symbol];
  1153. }
  1154.  
  1155.  
  1156. /*****************************************************************/
  1157. /*     Check whether or not there is a high probability that a   */
  1158. /* given string is a misspelling of another.                     */
  1159. /* Certain singleton symbols (such as ":" and ";") are also      */
  1160. /* considered to be misspelling of each other.                   */
  1161. /*****************************************************************/
  1162. int DiagnoseParser::Misspell(int sym, TokenObject tok)
  1163. {
  1164.     int len = name_length[terminal_index[sym]];
  1165.  
  1166.     wchar_t *keyword = new wchar_t[len + 1];
  1167.     for (int i = name_start[terminal_index[sym]], j = 0; j < len; i++, j++)
  1168.     {
  1169.         wchar_t c = string_buffer[i];
  1170.         keyword[j] = c;
  1171.     }
  1172.     keyword[len] = U_NULL;
  1173.  
  1174.     int index = Spell::Index(lex_stream -> NameString(tok), keyword);
  1175.  
  1176.     delete [] keyword;
  1177.  
  1178.     return index;
  1179. }
  1180.  
  1181.  
  1182. /*****************************************************************/
  1183. /*****************************************************************/
  1184. PrimaryRepairInfo DiagnoseParser::ScopeTrial(int stck[], int stack_top,
  1185.                                              PrimaryRepairInfo repair)
  1186. {
  1187.     state_seen = new int[stack_length];
  1188.     for (int i = 0; i < stack_length; i++)
  1189.         state_seen[i] = NIL;
  1190.  
  1191.     ScopeTrialCheck(stck, stack_top, repair, 0);
  1192.  
  1193.     delete [] state_seen;
  1194.     state_pool.Reset();
  1195.  
  1196.     repair.code = SCOPE_CODE;
  1197.     repair.misspell_index = 10;
  1198.  
  1199.     return repair;
  1200. }
  1201.  
  1202.  
  1203. /*****************************************************************/
  1204. /* SCOPE_TRIAL_CHECK is a recursive procedure that takes as arguments  */
  1205. /* a state configuration: STACK and STACK_TOP, and an integer:   */
  1206. /* INDX. In addition, a global variable SCOPE_DISTANCE indicates */
  1207. /* the distance to "beat" and SCOPE_BUFFER_POSITION identifies   */
  1208. /* the starting position of the next input tokens in BUFFER.     */
  1209. /* SCOPE_TRIAL determines whether or not scope recovery is       */
  1210. /* possible.  If so, it uses two global arrays: SCOPE_INDEX and  */
  1211. /* SCOPE_LOCATION to store the necessary information about the   */
  1212. /* scopes to be closed. A global variable, scope_stack_top, identifies */
  1213. /* the highest element used in these arrays.                     */
  1214. /* The global variable SCOPE_DISTANCE is also updated to reflect */
  1215. /* the new result.                                               */
  1216. /*****************************************************************/
  1217. void DiagnoseParser::ScopeTrialCheck(int stck[], int stack_top,
  1218.                                      PrimaryRepairInfo& repair, int indx)
  1219. {
  1220.     int max_pos,
  1221.         marked_pos,
  1222.         stack_position,
  1223.         distance,
  1224.         previous_distance,
  1225.         i,
  1226.         j,
  1227.         k,
  1228.         act,
  1229.         tok,
  1230.         lhs_symbol;
  1231.  
  1232.     act = stck[stack_top];
  1233.  
  1234.     for (i = state_seen[stack_top]; i != NIL; i = state_pool[i].next)
  1235.         if (state_pool[i].state == act)
  1236.             return;
  1237.  
  1238.     i = state_pool.NextIndex();
  1239.     state_pool[i].state = act;
  1240.     state_pool[i].next  = state_seen[stack_top];
  1241.     state_seen[stack_top] = i;
  1242.  
  1243.     for (i = 0; i < SCOPE_SIZE; i++)
  1244.     {
  1245.         /*********************************************************/
  1246.         /* Use the scope lookahead symbol to force all reductions*/
  1247.         /* inducible by that symbol.                             */
  1248.         /*********************************************************/
  1249.         act = stck[stack_top];
  1250.         temp_stack_top = stack_top - 1;
  1251.         max_pos = stack_top;
  1252.         tok = scope_la[i];
  1253.         lex_stream -> Reset(buffer[repair.buffer_position]);
  1254.         act = t_action(act, tok, lex_stream);
  1255.         while(act <= NUM_RULES)
  1256.         {
  1257.             /*************************************************/
  1258.             /* ... Process all goto-reduce actions following */
  1259.             /* reduction, until a goto action is computed ...*/
  1260.             /*************************************************/
  1261.             do
  1262.             {
  1263.                 temp_stack_top -= (rhs[act]-1);
  1264.                 lhs_symbol = lhs[act];
  1265.                 act =  (temp_stack_top > max_pos
  1266.                             ?  temp_stack[temp_stack_top]
  1267.                             :  stck[temp_stack_top]);
  1268.                 act = nt_action(act, lhs_symbol);
  1269.             }  while(act <= NUM_RULES);
  1270.             if (temp_stack_top + 1 >= stack_length)
  1271.                 return;
  1272.             max_pos = Min(max_pos, temp_stack_top);
  1273.             temp_stack[temp_stack_top + 1] = act;
  1274.             act = t_action(act, tok, lex_stream);
  1275.         }
  1276.  
  1277.         /*********************************************************/
  1278.         /* If the lookahead symbol is parsable, then we check    */
  1279.         /* whether or not we have a match between the scope      */
  1280.         /* prefix and the transition symbols corresponding to    */
  1281.         /* the states on top of the stack.                       */
  1282.         /*********************************************************/
  1283.         if (act != ERROR_ACTION)
  1284.         {
  1285.             k = scope_prefix[i];
  1286.             for (j = temp_stack_top + 1;
  1287.                  j >= (max_pos + 1) &&
  1288.                  in_symbol(temp_stack[j]) == scope_rhs[k]; j--)
  1289.                  k++;
  1290.             if (j == max_pos)
  1291.                 for (j = max_pos;
  1292.                      j >= 1 && in_symbol(stck[j]) == scope_rhs[k];
  1293.                      j--)
  1294.                     k++;
  1295.             /*****************************************************/
  1296.             /* If the prefix matches, check whether the state    */
  1297.             /* newly exposed on top of the stack, (after the     */
  1298.             /* corresponding prefix states are popped from the   */
  1299.             /* stack), is in the set of "source states" for the  */
  1300.             /* scope in question and that it is at a position    */
  1301.             /* below the threshold indicated by MARKED_POS.      */
  1302.             /*****************************************************/
  1303.             marked_pos = (max_pos < stack_top ? max_pos + 1
  1304.                                               : stack_top);
  1305.             if (scope_rhs[k] == 0 && j < marked_pos)   /* match? */
  1306.             {
  1307.                 stack_position = j;
  1308.                 for (j = scope_state_set[i];
  1309.                      stck[stack_position] != scope_state[j] &&
  1310.                      scope_state[j] != 0;
  1311.                      j++);
  1312.                 /*************************************************/
  1313.                 /* If the top state is valid for scope recovery, */
  1314.                 /* the left-hand side of the scope is used as    */
  1315.                 /* starting symbol and we calculate how far the  */
  1316.                 /* parser can advance within the forward context */
  1317.                 /* after parsing the left-hand symbol.           */
  1318.                 /*************************************************/
  1319.                 if (scope_state[j] != 0)      /* state was found */
  1320.                 {
  1321.                     previous_distance = repair.distance;
  1322.                     distance = ParseCheck(stck,
  1323.                                           stack_position,
  1324.                                           scope_lhs[i]+NT_OFFSET,
  1325.                                           repair.buffer_position);
  1326.                     /*********************************************/
  1327.                     /* if the recovery is not successful, we     */
  1328.                     /* update the stack with all actions induced */
  1329.                     /* by the left-hand symbol, and recursively  */
  1330.                     /* call SCOPE_TRIAL_CHECK to try again.      */
  1331.                     /* Otherwise, the recovery is successful. If */
  1332.                     /* the new distance is greater than the      */
  1333.                     /* initial SCOPE_DISTANCE, we update         */
  1334.                     /* SCOPE_DISTANCE and set scope_stack_top to INDX  */
  1335.                     /* to indicate the number of scopes that are */
  1336.                     /* to be applied for a succesful  recovery.  */
  1337.                     /* NOTE that this procedure cannot get into  */
  1338.                     /* an infinite loop, since each prefix match */
  1339.                     /* is guaranteed to take us to a lower point */
  1340.                     /* within the stack.                         */
  1341.                     /*********************************************/
  1342.                     if ((distance - repair.buffer_position + 1) <
  1343.                         MIN_DISTANCE)
  1344.                     {
  1345.                         int top = stack_position;
  1346.                         act = nt_action(stck[top], scope_lhs[i]);
  1347.                         while(act <= NUM_RULES)
  1348.                         {
  1349.                             top -= (rhs[act]-1);
  1350.                             act = nt_action(stck[top], lhs[act]);
  1351.                         }
  1352.                         top++;
  1353.  
  1354.                         j = act;
  1355.                         act = stck[top];  /* save */
  1356.                         stck[top] = j;    /* swap */
  1357.                         ScopeTrialCheck(stck, top, repair, indx+1);
  1358.                         stck[top] = act; /* restore */
  1359.                     }
  1360.                     else if (distance > repair.distance)
  1361.                     {
  1362.                         scope_stack_top = indx;
  1363.                         repair.distance = distance;
  1364.                     }
  1365.  
  1366.                     if (lex_stream -> Kind(buffer[repair.buffer_position]) ==
  1367.                         EOFT_SYMBOL &&
  1368.                         repair.distance == previous_distance)
  1369.                     {
  1370.                         scope_stack_top = indx;
  1371.                         repair.distance = MAX_DISTANCE;
  1372.                     }
  1373.  
  1374.                     /*********************************************/
  1375.                     /* If this scope recovery has beaten the     */
  1376.                     /* previous distance, then we have found a   */
  1377.                     /* better recovery (or this recovery is one  */
  1378.                     /* of a list of scope recoveries). Record    */
  1379.                     /* its information at the proper location    */
  1380.                     /* (INDX) in SCOPE_INDEX and SCOPE_STACK.    */
  1381.                     /*********************************************/
  1382.                     if (repair.distance > previous_distance)
  1383.                     {
  1384.                         scope_index[indx] = i;
  1385.                         scope_position[indx] = stack_position;
  1386.                         return;
  1387.                     }
  1388.                 }
  1389.             }
  1390.         }
  1391.     }
  1392.  
  1393.     return;
  1394. }
  1395.  
  1396. /*****************************************************************/
  1397. /* This function computes the ParseCheck distance for the best   */
  1398. /* possible secondary recovery for a given configuration that    */
  1399. /* either deletes none or only one symbol in the forward context.*/
  1400. /* If the recovery found is more effective than the best primary */
  1401. /* recovery previously computed, then the function returns true. */
  1402. /* Only misplacement, scope and manual recoveries are attempted; */
  1403. /* simple insertion or substitution of a nonterminal are tried   */
  1404. /* in CHECK_PRIMARY_DISTANCE as part of primary recovery.        */
  1405. /*****************************************************************/
  1406. bool DiagnoseParser::SecondaryCheck(int stck[], int stack_top,
  1407.                                     int buffer_position, int distance)
  1408. {
  1409.     PrimaryRepairInfo repair;
  1410.  
  1411.     int top,
  1412.         j;
  1413.  
  1414.     for (top = stack_top - 1; top >= 0; top--)
  1415.     {
  1416.         j = ParseCheck(stck, top,
  1417.                        lex_stream -> Kind(buffer[buffer_position]),
  1418.                        buffer_position + 1);
  1419.         if (((j - buffer_position + 1) > MIN_DISTANCE) &&
  1420.             (j > distance))
  1421.             return true;
  1422.     }
  1423.  
  1424. #if defined(SCOPE_REPAIR)
  1425.     repair.buffer_position = buffer_position + 1;
  1426.     repair.distance = distance;
  1427.     repair = ScopeTrial(stck, stack_top, repair);
  1428.     if ((repair.distance - buffer_position) > MIN_DISTANCE &&
  1429.         repair.distance > distance)
  1430.          return true;
  1431. //#elif !defined(SCOPE_REPAIR)
  1432. //    manual_buffer_position = buffer_position + 1;
  1433. //    manual_distance = distance;
  1434. //    manual_trial(stck, stack_top);
  1435. //    if ((manual_distance - repair.buffer_position) > MIN_DISTANCE &&
  1436. //        manual_distance > distance)
  1437. //         return true;
  1438. #endif
  1439.  
  1440.     return false;
  1441. }
  1442.  
  1443.  
  1444. /*****************************************************************/
  1445. /* Secondary_phase is a boolean function that checks whether or  */
  1446. /* not some form of secondary recovery is applicable to one of   */
  1447. /* the error configurations. First, if "next_stack" is available,*/
  1448. /* misplacement and secondary recoveries are attempted on it.    */
  1449. /* Then, in any case, these recoveries are attempted on "stack". */
  1450. /* If a successful recovery is found, a diagnosis is issued, the */
  1451. /* configuration is updated and the function returns "true".     */
  1452. /* Otherwise, the function returns false.                        */
  1453. /*****************************************************************/
  1454. RepairCandidate DiagnoseParser::SecondaryPhase(TokenObject error_token)
  1455. {
  1456.     SecondaryRepairInfo repair,
  1457.                           misplaced;
  1458.  
  1459.     RepairCandidate candidate;
  1460.  
  1461.     int i,
  1462.         j,
  1463.         k,
  1464.         top,
  1465.         next_last_index,
  1466.         last_index;
  1467.  
  1468.     candidate.symbol = 0;
  1469.  
  1470.     repair.code = 0;
  1471.     repair.distance = 0;
  1472.     repair.recovery_on_next_stack = false;
  1473.  
  1474.     misplaced.distance = 0;
  1475.     misplaced.recovery_on_next_stack = false;
  1476.  
  1477. /*****************************************************************/
  1478. /* If the next_stack is available, try misplaced and secondary   */
  1479. /* recovery on it first.                                         */
  1480. /*****************************************************************/
  1481.     if (next_stack_top >= 0)
  1482.     {
  1483.         Location  save_location;
  1484.  
  1485.         buffer[2] = error_token;
  1486.         buffer[1] = lex_stream -> Previous(buffer[2]);
  1487.         buffer[0] = lex_stream -> Previous(buffer[1]);
  1488.  
  1489.         for (k = 3; k < BUFF_UBOUND; k++)
  1490.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1491.  
  1492.         buffer[BUFF_UBOUND] = lex_stream -> Badtoken();/* elmt not available */
  1493.  
  1494.         /*********************************************************/
  1495.         /* If we are at the end of the input stream, compute the */
  1496.         /* index position of the first EOFT symbol (last useful  */
  1497.         /* index).                                               */
  1498.         /*********************************************************/
  1499.         for (next_last_index = MAX_DISTANCE - 1;
  1500.              next_last_index >= 1 &&
  1501.              lex_stream -> Kind(buffer[next_last_index]) == EOFT_SYMBOL;
  1502.              next_last_index--);
  1503.         next_last_index = next_last_index + 1;
  1504.  
  1505.         save_location = location_stack[next_stack_top];
  1506.         location_stack[next_stack_top] = Loc(buffer[2]);
  1507.         misplaced.num_deletions = next_stack_top;
  1508.         misplaced = MisplacementRecovery(next_stack, next_stack_top,
  1509.                                          next_last_index,
  1510.                                          misplaced, true);
  1511.         if (misplaced.recovery_on_next_stack)
  1512.             misplaced.distance++;
  1513.  
  1514.         repair.num_deletions = next_stack_top + BUFF_UBOUND;
  1515.         repair = SecondaryRecovery(next_stack, next_stack_top,
  1516.                                    next_last_index,
  1517.                                    repair, true);
  1518.         if (repair.recovery_on_next_stack)
  1519.             repair.distance++;
  1520.  
  1521.         location_stack[next_stack_top] = save_location;
  1522.     }
  1523.     else             /* next_stack not available, initialize ... */
  1524.     {
  1525.         misplaced.num_deletions = state_stack_top;
  1526.         repair.num_deletions = state_stack_top + BUFF_UBOUND;
  1527.     }
  1528.  
  1529. /*****************************************************************/
  1530. /* Try secondary recovery on the "stack" configuration.          */
  1531. /*****************************************************************/
  1532.     buffer[3] = error_token;
  1533.  
  1534.     buffer[2] = lex_stream -> Previous(buffer[3]);
  1535.     buffer[1] = lex_stream -> Previous(buffer[2]);
  1536.     buffer[0] = lex_stream -> Previous(buffer[1]);
  1537.  
  1538.     for (k = 4; k < BUFF_SIZE; k++)
  1539.         buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1540.  
  1541.     for (last_index = MAX_DISTANCE - 1;
  1542.          last_index >= 1 && lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL;
  1543.          last_index--);
  1544.     last_index++;
  1545.  
  1546.     misplaced = MisplacementRecovery(stack, state_stack_top,
  1547.                                      last_index,
  1548.                                      misplaced, false);
  1549.  
  1550.     repair = SecondaryRecovery(stack, state_stack_top,
  1551.                                last_index, repair, false);
  1552.  
  1553. /*****************************************************************/
  1554. /* If a successful misplaced recovery was found, compare it with */
  1555. /* the most successful secondary recovery.  If the misplaced     */
  1556. /* recovery either deletes fewer symbols or parse-checks further */
  1557. /* then it is chosen.                                            */
  1558. /*****************************************************************/
  1559.     if (misplaced.distance > MIN_DISTANCE)
  1560.     {
  1561.         if (misplaced.num_deletions <= repair.num_deletions ||
  1562.            (misplaced.distance - misplaced.num_deletions) >=
  1563.            (repair.distance - repair.num_deletions))
  1564.         {
  1565.             repair.code = MISPLACED_CODE;
  1566.             repair.stack_position = misplaced.stack_position;
  1567.             repair.buffer_position = 2;
  1568.             repair.num_deletions = misplaced.num_deletions;
  1569.             repair.distance = misplaced.distance;
  1570.             repair.recovery_on_next_stack = misplaced.recovery_on_next_stack;
  1571.         }
  1572.     }
  1573.  
  1574. /*****************************************************************/
  1575. /* If the successful recovery was on next_stack, update: stack,  */
  1576. /* buffer, location_stack and last_index.                        */
  1577. /*****************************************************************/
  1578.     if (repair.recovery_on_next_stack)
  1579.     {
  1580.         state_stack_top = next_stack_top;
  1581.         for (i = 0; i <= state_stack_top; i++)
  1582.             stack[i] = next_stack[i];
  1583.  
  1584.         buffer[2] = error_token;
  1585.         buffer[1] = lex_stream -> Previous(buffer[2]);
  1586.         buffer[0] = lex_stream -> Previous(buffer[1]);
  1587.  
  1588.         for (k = 3; k < BUFF_UBOUND; k++)
  1589.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  1590.  
  1591.         buffer[BUFF_UBOUND] = lex_stream -> Badtoken();/* elmt not available */
  1592.  
  1593.         location_stack[next_stack_top] = Loc(buffer[2]);
  1594.         last_index = next_last_index;
  1595.     }
  1596.  
  1597. #if defined(SCOPE_REPAIR)
  1598. /*****************************************************************/
  1599. /* Next, try scope recoveries after deletion of one, two, three, */
  1600. /* four ... buffer_position tokens from the input stream.        */
  1601. /*****************************************************************/
  1602.     if (repair.code == SECONDARY_CODE ||
  1603.         repair.code == DELETION_CODE)
  1604.     {
  1605.         PrimaryRepairInfo scope_repair;
  1606.  
  1607.         scope_repair.distance = 0;
  1608.         for (scope_repair.buffer_position = 2;
  1609.              scope_repair.buffer_position <= repair.buffer_position &&
  1610.              repair.code != SCOPE_CODE; scope_repair.buffer_position++)
  1611.         {
  1612.             scope_repair = ScopeTrial(stack, state_stack_top, scope_repair);
  1613.             j = (scope_repair.distance == MAX_DISTANCE
  1614.                                         ? last_index
  1615.                                         : scope_repair.distance);
  1616.             k = scope_repair.buffer_position - 1;
  1617.             if ((j - k) > MIN_DISTANCE &&
  1618.                 (j - k) > (repair.distance - repair.num_deletions))
  1619.             {
  1620.                 repair.code = SCOPE_CODE;
  1621.                 i = scope_index[scope_stack_top];       /* upper bound */
  1622.                 repair.symbol = scope_lhs[i] + NT_OFFSET;
  1623.                 repair.stack_position = state_stack_top;
  1624.                 repair.buffer_position = scope_repair.buffer_position;
  1625.             }
  1626.         }
  1627.     }
  1628.  
  1629. /*****************************************************************/
  1630. /* If no successful recovery is found and we have reached the    */
  1631. /* end of the file, check whether or not scope recovery is       */
  1632. /* applicable at the end of the file after discarding some       */
  1633. /* states.                                                       */
  1634. /*****************************************************************/
  1635.     if (repair.code == 0 &&
  1636.         lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL)
  1637.     {
  1638.         PrimaryRepairInfo scope_repair;
  1639.  
  1640.         scope_repair.buffer_position = last_index;
  1641.         scope_repair.distance = 0;
  1642.         for (top = state_stack_top;
  1643.              top >= 0 && repair.code == 0; top--)
  1644.         {
  1645.             scope_repair = ScopeTrial(stack, top, scope_repair);
  1646.             if (scope_repair.distance > 0)
  1647.             {
  1648.                 repair.code = SCOPE_CODE;
  1649.                 i = scope_index[scope_stack_top];    /* upper bound */
  1650.                 repair.symbol = scope_lhs[i] + NT_OFFSET;
  1651.                 repair.stack_position = top;
  1652.                 repair.buffer_position = scope_repair.buffer_position;
  1653.             }
  1654.         }
  1655.     }
  1656.  
  1657. #endif
  1658.  
  1659. /*****************************************************************/
  1660. /* If a successful repair was not found, quit!  Otherwise, issue */
  1661. /* diagnosis and adjust configuration...                         */
  1662. /*****************************************************************/
  1663.     if (repair.code == 0)
  1664.         return candidate;
  1665.  
  1666.     SecondaryDiagnosis(repair);
  1667.  
  1668. /*****************************************************************/
  1669. /* Update buffer based on number of elements that are deleted.   */
  1670. /*****************************************************************/
  1671.     switch(repair.code)
  1672.     {
  1673.         case MANUAL_CODE: case MISPLACED_CODE:
  1674.              candidate.location = Loc(buffer[2]);
  1675.              candidate.symbol = lex_stream -> Kind(buffer[2]);
  1676.              lex_stream -> Reset(lex_stream -> Next(buffer[2]));
  1677.  
  1678.              break;
  1679.  
  1680.         case DELETION_CODE:
  1681.              candidate.location = Loc(buffer[repair.buffer_position]);
  1682.              candidate.symbol =
  1683.                        lex_stream -> Kind(buffer[repair.buffer_position]);
  1684.              lex_stream -> Reset(lex_stream -> Next(buffer[repair.buffer_position]));
  1685.  
  1686.              break;
  1687.  
  1688.         default: /* SCOPE_CODE || SECONDARY_CODE */
  1689.              candidate.symbol = repair.symbol;
  1690.              candidate.location = Loc(buffer[repair.buffer_position]);
  1691.              lex_stream -> Reset(buffer[repair.buffer_position]);
  1692.  
  1693.              break;
  1694.     }
  1695.  
  1696.     return candidate;
  1697. }
  1698.  
  1699.  
  1700. /*****************************************************************/
  1701. /* This boolean function checks whether or not a given           */
  1702. /* configuration yields a better misplacement recovery than      */
  1703. /* the best misplacement recovery computed previously.           */
  1704. /*****************************************************************/
  1705. SecondaryRepairInfo DiagnoseParser::MisplacementRecovery
  1706.          (int stck[], int stack_top, int last_index,
  1707.           SecondaryRepairInfo repair, bool stack_flag)
  1708. {
  1709.     Location  previous_loc = Loc(buffer[2]);
  1710.     int stack_deletions = 0;
  1711.  
  1712.     for (int top = stack_top - 1; top >= 0; top--)
  1713.     {
  1714.         if (location_stack[top] < previous_loc)
  1715.             stack_deletions++;
  1716.         previous_loc = location_stack[top];
  1717.  
  1718.         int j = ParseCheck(stck, top, lex_stream -> Kind(buffer[2]), 3);
  1719.         if (j == MAX_DISTANCE)
  1720.              j = last_index;
  1721.         if ((j > MIN_DISTANCE) &&
  1722.             (j - stack_deletions) >
  1723.             (repair.distance - repair.num_deletions))
  1724.         {
  1725.             repair.stack_position = top;
  1726.             repair.distance = j;
  1727.             repair.num_deletions = stack_deletions;
  1728.             repair.recovery_on_next_stack = stack_flag;
  1729.         }
  1730.     }
  1731.  
  1732.     return repair;
  1733. }
  1734.  
  1735.  
  1736. /*****************************************************************/
  1737. /* This boolean function checks whether or not a given           */
  1738. /* configuration yields a better secondary recovery than the     */
  1739. /* best misplacement recovery computed previously.               */
  1740. /*****************************************************************/
  1741. SecondaryRepairInfo DiagnoseParser::SecondaryRecovery
  1742.          (int stck[],int stack_top,
  1743.           int last_index, SecondaryRepairInfo repair, bool stack_flag)
  1744. {
  1745.     int i,
  1746.         j,
  1747.         k,
  1748.         l,
  1749.         symbol,
  1750.         stack_deletions,
  1751.         top;
  1752.  
  1753.     Location  previous_loc;
  1754.  
  1755.     stack_deletions = 0;
  1756.     previous_loc = Loc(buffer[2]);
  1757.     for (top = stack_top;
  1758.          top >= 0 && repair.num_deletions >= stack_deletions; top--)
  1759.     {
  1760.         if (location_stack[top] < previous_loc)
  1761.             stack_deletions++;
  1762.         previous_loc = location_stack[top];
  1763.  
  1764.         for (i = 2;
  1765.              i <= (last_index - MIN_DISTANCE + 1) &&
  1766.              (repair.num_deletions >= (stack_deletions + i - 1)); i++)
  1767.         {
  1768.             j = ParseCheck(stck, top, lex_stream -> Kind(buffer[i]), i + 1);
  1769.  
  1770.             if (j == MAX_DISTANCE)
  1771.                  j = last_index;
  1772.             if ((j - i + 1) > MIN_DISTANCE)
  1773.             {
  1774.                 k = stack_deletions + i - 1;
  1775.                 if ((k < repair.num_deletions) ||
  1776.                     (j - k) > (repair.distance - repair.num_deletions) ||
  1777.                     ((repair.code == SECONDARY_CODE) &&
  1778.                      (j - k) == (repair.distance -
  1779.                                  repair.num_deletions)))
  1780.                 {
  1781.                     repair.code = DELETION_CODE;
  1782.                     repair.distance = j;
  1783.                     repair.stack_position = top;
  1784.                     repair.buffer_position = i;
  1785.                     repair.num_deletions = k;
  1786.                     repair.recovery_on_next_stack = stack_flag;
  1787.                 }
  1788.             }
  1789.  
  1790.             for (l = nasi(stck[top]); l >= 0 && nasr[l] != 0; l++)
  1791.             {
  1792.                 symbol = nasr[l] + NT_OFFSET;
  1793.                 j = ParseCheck(stck, top, symbol, i);
  1794.                 if (j == MAX_DISTANCE)
  1795.                      j = last_index;
  1796.                 if ((j - i + 1) > MIN_DISTANCE)
  1797.                 {
  1798.                     k = stack_deletions + i - 1;
  1799.                     if (k < repair.num_deletions ||
  1800.                        (j - k) > (repair.distance -
  1801.                                   repair.num_deletions))
  1802.                     {
  1803.                         repair.code = SECONDARY_CODE;
  1804.                         repair.symbol = symbol;
  1805.                         repair.distance = j;
  1806.                         repair.stack_position = top;
  1807.                         repair.buffer_position = i;
  1808.                         repair.num_deletions = k;
  1809.                         repair.recovery_on_next_stack = stack_flag;
  1810.                     }
  1811.                 }
  1812.             }
  1813.         }
  1814.     }
  1815.  
  1816.     return repair;
  1817. }
  1818.  
  1819.  
  1820. /*****************************************************************/
  1821. /* This procedure is invoked to issue a secondary diagnosis and  */
  1822. /* adjust the input buffer.  The recovery in question is either  */
  1823. /* an automatic scope recovery, a manual scope recovery, a       */
  1824. /* secondary substitution or a secondary deletion.               */
  1825. /*****************************************************************/
  1826. void DiagnoseParser::SecondaryDiagnosis(SecondaryRepairInfo repair)
  1827. {
  1828. /*****************************************************************/
  1829. /*  Issue diagnostic.                                            */
  1830. /*****************************************************************/
  1831.     switch(repair.code)
  1832. #if defined(SCOPE_REPAIR)
  1833.     {
  1834.         case SCOPE_CODE:
  1835.         {
  1836.             if (repair.stack_position < state_stack_top)
  1837.             {
  1838.                 error.Report(0, DELETION_CODE,
  1839.                                 terminal_index[ERROR_SYMBOL],
  1840.                                 location_stack[repair.stack_position],
  1841.                                 buffer[1]);
  1842. //                set_location(buffer[1],
  1843. //                             location_stack[repair.stack_position]);
  1844.             }
  1845.             for (int i = 0; i < scope_stack_top; i++)
  1846.             {
  1847.                 error.Report(0, SCOPE_CODE,
  1848.                                 -scope_index[i],
  1849.                                 location_stack[scope_position[i]],
  1850.                                 buffer[1],
  1851.                                 non_terminal_index[scope_lhs[scope_index[i]]]);
  1852.             }
  1853.  
  1854.             repair.symbol = scope_lhs[scope_index[scope_stack_top]] + NT_OFFSET;
  1855.             state_stack_top = scope_position[scope_stack_top];
  1856.             error.Report(0, SCOPE_CODE,
  1857.                             -scope_index[scope_stack_top],
  1858.                             location_stack[scope_position[scope_stack_top]],
  1859.                             buffer[1],
  1860.                             GetNtermIndex(stack[state_stack_top],
  1861.                                           repair.symbol,
  1862.                                           repair.buffer_position)
  1863.                            );
  1864.             break;
  1865.         }
  1866. #endif
  1867.         default:
  1868.         {
  1869.             error.Report(0, repair.code,
  1870.                             (repair.code == SECONDARY_CODE
  1871.                                           ? GetNtermIndex(stack[repair.stack_position],
  1872.                                                           repair.symbol,
  1873.                                                           repair.buffer_position)
  1874.                                           : terminal_index[ERROR_SYMBOL]),
  1875.                             location_stack[repair.stack_position],
  1876.                             buffer[repair.buffer_position - 1]);
  1877.             state_stack_top = repair.stack_position;
  1878.         }
  1879.     }
  1880.  
  1881.     return;
  1882. }
  1883.  
  1884.  
  1885. //
  1886. // This procedure uses a  quick sort algorithm to sort the ERRORS
  1887. // by the left_line_no and left_column_no fields.
  1888. //
  1889. void ParseError::SortMessages()
  1890. {
  1891.      int lower,
  1892.          upper,
  1893.          lostack[32],
  1894.          histack[32];
  1895.  
  1896.      int top,
  1897.          i,
  1898.          j;
  1899.      ErrorInfo pivot, temp;
  1900.  
  1901.      top = 0;
  1902.      lostack[top] = 0;
  1903.      histack[top] = errors.Length() - 1;
  1904.  
  1905.      while(top >= 0)
  1906.      {
  1907.          lower = lostack[top];
  1908.          upper = histack[top];
  1909.          top--;
  1910.  
  1911.          while(upper > lower)
  1912.          {
  1913.              /*********************************************************/
  1914.              /* The array is most-likely almost sorted. Therefore,    */
  1915.              /* we use the middle element as the pivot element.       */
  1916.              /*********************************************************/
  1917.              i = (lower + upper) / 2;
  1918.              pivot = errors[i];
  1919.              errors[i] = errors[lower];
  1920.  
  1921.              /*********************************************************/
  1922.              /* Split the array section indicated by LOWER and UPPER  */
  1923.              /* using ARRAY(LOWER) as the pivot.                      */
  1924.              /*********************************************************/
  1925.              i = lower;
  1926.              for (j = lower + 1; j <= upper; j++)
  1927.                  if ((errors[j].left_token < pivot.left_token) ||
  1928.                  /*****************************************************/
  1929.                  /* When two error messages start in the same location*/
  1930.                  /* and one is nested inside the other, the outer one */
  1931.                  /* is placed first so that it can be printed last.   */
  1932.                  /* Recall that its right-span location is reached    */
  1933.                  /* after the inner one has been completely processed.*/
  1934.                  /*****************************************************/
  1935.                      (errors[j].left_token == pivot.left_token &&
  1936.                       errors[j].right_token > pivot.right_token) ||
  1937.                  /*****************************************************/
  1938.                  /* When two error messages are at the same location  */
  1939.                  /* span, check the NUM field to keep the sort stable.*/
  1940.                  /* When the location spans only a single symbol,     */
  1941.                  /* the one with the lowest "num" is placed first.    */
  1942.                  /*****************************************************/
  1943.                      (errors[j].left_token  == pivot.left_token  &&
  1944.                       errors[j].right_token == pivot.right_token &&
  1945.                       pivot.left_token == pivot.right_token     &&
  1946.                       errors[j].num < pivot.num)                       ||
  1947.                  /*****************************************************/
  1948.                  /* When two error messages are at the same location  */
  1949.                  /* which spans more than one symbol in the source,   */
  1950.                  /* the first message is treated as been nested into  */
  1951.                  /* the second message and (just like the nested case */
  1952.                  /* above) it is placed last in the sorted sequence.  */
  1953.                  /*****************************************************/
  1954.                      (errors[j].left_token  == pivot.left_token  &&
  1955.                       errors[j].right_token == pivot.right_token &&
  1956.                       pivot.left_token < pivot.right_token      &&
  1957.                       errors[j].num > pivot.num))
  1958.                  {
  1959.                      temp = errors[++i];
  1960.                      errors[i] = errors[j];
  1961.                      errors[j] = temp;
  1962.                  }
  1963.              errors[lower] = errors[i];
  1964.              errors[i] = pivot;
  1965.  
  1966.              top++;
  1967.              if ((i - lower) < (upper - i))
  1968.              {
  1969.                  lostack[top] = i + 1;
  1970.                  histack[top] = upper;
  1971.                  upper = i - 1;
  1972.              }
  1973.              else
  1974.              {
  1975.                  histack[top] = i - 1;
  1976.                  lostack[top] = lower;
  1977.                  lower = i + 1;
  1978.              }
  1979.          }
  1980.      }
  1981.  
  1982.      return;
  1983. }
  1984.  
  1985.  
  1986. /*****************************************************************/
  1987. /* This procedure is invoked by an JIKES PARSER or a semantic    */
  1988. /* routine to process an error message.  The JIKES parser always */
  1989. /* passes the value 0 to msg_level to indicate an error.         */
  1990. /* This routine simply stores all necessary information about    */
  1991. /* the message into an array: error.                             */
  1992. /*****************************************************************/
  1993. void ParseError::Report(int msg_level,
  1994.                         int msg_code,
  1995.                         int name_index,
  1996.                         LexStream::TokenIndex left_token,
  1997.                         LexStream::TokenIndex right_token,
  1998.                         int scope_name_index)
  1999. {
  2000.     int i = errors.NextIndex();
  2001.  
  2002.     errors[i].msg_level           = msg_level;
  2003.     errors[i].msg_code            = msg_code;
  2004.     errors[i].name_index          = name_index;
  2005.     errors[i].num                 = i;
  2006.     errors[i].left_token          = (left_token > Loc(right_token) ? Loc(right_token) : left_token);
  2007.     errors[i].right_token         = Loc(right_token);
  2008.     errors[i].right_string_length = lex_stream -> NameStringLength(right_token);
  2009.     errors[i].scope_name_index    = scope_name_index;
  2010.  
  2011.     if (control.option.dump_errors)
  2012.     {
  2013.         if (errors[i].left_token < errors[i].right_token)
  2014.              PrintSecondaryMessage(i);
  2015.         else PrintPrimaryMessage(i);
  2016.         errors.Reset(1); // we only need to indicate that at least one error was detected... See print_messages
  2017.         Coutput.flush();
  2018.     }
  2019.  
  2020.     return;
  2021. }
  2022.  
  2023.  
  2024. /*****************************************************************/
  2025. /* This procedure is invoked to print JIKES error messages that  */
  2026. /* have been stored in the array: error.                         */
  2027. /*****************************************************************/
  2028. void ParseError::PrintMessages()
  2029. {
  2030.     if (control.option.dump_errors || errors.Length() == 0)
  2031.     {
  2032.         Coutput.flush();
  2033.         return;
  2034.     }
  2035.  
  2036.     if (control.option.errors)
  2037.     {
  2038.         Coutput << "\nFound " << errors.Length() << " syntax error" << (errors.Length() == 1 ? "" : "s")
  2039.                 << " in \""
  2040.                 << lex_stream -> FileName()
  2041.                 << "\":";
  2042.  
  2043.         lex_stream -> RereadInput();
  2044.  
  2045.         if (! lex_stream -> InputBuffer())
  2046.         {
  2047.             char *file_name = lex_stream -> FileName();
  2048.             int length = lex_stream -> FileNameLength();
  2049.             wchar_t *name = new wchar_t[length + 1];
  2050.             for (int i = 0; i < length; i++)
  2051.                 name[i] = file_name[i];
  2052.             name[length] = U_NULL;
  2053.             control.system_semantic -> ReportSemError(SemanticError::CANNOT_REOPEN_FILE,
  2054.                                                       0,
  2055.                                                       0,
  2056.                                                       name);
  2057.             delete [] name;
  2058.             return;
  2059.         }
  2060.     }
  2061.     else if (! lex_stream -> ComputeColumns())
  2062.     {
  2063.         char *file_name = lex_stream -> FileName();
  2064.         int length = lex_stream -> FileNameLength();
  2065.         wchar_t *name = new wchar_t[length + 1];
  2066.         for (int i = 0; i < length; i++)
  2067.             name[i] = file_name[i];
  2068.         name[length] = U_NULL;
  2069.         control.system_semantic -> ReportSemError(SemanticError::CANNOT_COMPUTE_COLUMNS,
  2070.                                                   0,
  2071.                                                   0,
  2072.                                                   name);
  2073.         delete [] name;
  2074.     }
  2075.  
  2076.     SortMessages();
  2077.  
  2078.     int stack_top = -1;
  2079.     int *error_stack = new int[errors.Length()];
  2080.  
  2081.     for (int k = 0; k < errors.Length(); k++)
  2082.     {
  2083.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2084.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2085.             right_column_no = lex_stream -> Column(errors[k].right_token),
  2086.             msg_code        = errors[k].msg_code;
  2087.  
  2088.         Location left_token = errors[k].left_token;
  2089.  
  2090.         for (; stack_top >= 0 && (errors[error_stack[stack_top]].right_token <= left_token); stack_top--)
  2091.         {
  2092.              if (stack_top == 0)
  2093.                  PrintLargeMessage(error_stack[stack_top]);
  2094.              else
  2095.              {
  2096.                  int i = error_stack[stack_top],
  2097.                      j = error_stack[stack_top - 1];
  2098.  
  2099.                  if ((errors[i].msg_code != SECONDARY_CODE &&
  2100.                       errors[i].msg_code != MISPLACED_CODE &&
  2101.                       errors[i].msg_code != DELETION_CODE) ||
  2102.                      (errors[j].msg_code != DELETION_CODE  &&
  2103.                       errors[j].msg_code != MISPLACED_CODE &&
  2104.                       errors[j].msg_code != SECONDARY_CODE))
  2105.                      PrintLargeMessage(i);
  2106.              }
  2107.         }
  2108.  
  2109.         if (errors[k].left_token < errors[k].right_token)
  2110.         {
  2111.             stack_top++;
  2112.             error_stack[stack_top] = k;
  2113.         }
  2114.         else if ((stack_top >= 0) &&
  2115.                  (errors[error_stack[stack_top]].msg_code ==
  2116.                   SECONDARY_CODE ||
  2117.                   errors[error_stack[stack_top]].msg_code ==
  2118.                   DELETION_CODE) &&
  2119.                  (errors[k].left_token ==
  2120.                       errors[error_stack[stack_top]].left_token ||
  2121.                   errors[k].right_token ==
  2122.                       errors[error_stack[stack_top]].right_token));
  2123.         else /* NOTE that input_line already contains a '\n' character */
  2124.         {
  2125.             if (control.option.errors)
  2126.             {
  2127.                 int m = left_column_no,
  2128.                     n = right_column_no + errors[k].right_string_length - 1;
  2129.  
  2130.                 Coutput << "\n\n";
  2131.                 Coutput.width(6);
  2132.                 Coutput << left_line_no << ". ";
  2133.                 for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2134.                     Coutput << lex_stream -> InputBuffer()[i];
  2135.  
  2136.                 if ((msg_code == SUBSTITUTION_CODE) ||
  2137.                     (n == m) ||
  2138.                     (msg_code == BEFORE_CODE)  ||
  2139.                     (msg_code == INVALID_CODE  && n <= (m+1)) ||
  2140.                     (msg_code == DELETION_CODE &&
  2141.                      left_column_no == right_column_no))
  2142.                 {
  2143.                     Coutput.width(left_column_no + 9);
  2144.                     Coutput << "^\n";
  2145.                 }
  2146.                 else if (msg_code == INSERTION_CODE ||
  2147.                          msg_code == EOF_CODE)
  2148.                 {
  2149.                     Coutput.width(n + 9);
  2150.                     Coutput << "^\n";
  2151.                 }
  2152.                 else
  2153.                 {
  2154.                     int offset = lex_stream -> WcharOffset(errors[k].left_token, errors[k].right_token);
  2155.                     Coutput.width(left_column_no + 8);
  2156.                     Coutput << "<";
  2157.                     Coutput.width(right_column_no + errors[k].right_string_length - left_column_no + offset);
  2158.                     Coutput.fill('-');
  2159.                     Coutput << (msg_code == SCOPE_CODE || msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2160.                     Coutput.fill(' ');
  2161.                 }
  2162.             }
  2163.  
  2164.             PrintPrimaryMessage(k);
  2165.         }
  2166.     }
  2167.  
  2168.     for (; stack_top > 0; stack_top--)
  2169.     {
  2170.         int i = error_stack[stack_top],
  2171.             j = error_stack[stack_top - 1];
  2172.  
  2173.         if ((errors[i].msg_code != SECONDARY_CODE &&
  2174.              errors[i].msg_code != DELETION_CODE) ||
  2175.             (errors[j].msg_code != DELETION_CODE  &&
  2176.              errors[j].msg_code != SECONDARY_CODE))
  2177.            PrintLargeMessage(i);
  2178.     }
  2179.     if (stack_top == 0)
  2180.         PrintLargeMessage(error_stack[stack_top]);
  2181.  
  2182.     Coutput.flush();
  2183.  
  2184.     delete [] error_stack;
  2185.  
  2186.     if (control.option.errors)
  2187.         lex_stream -> DestroyInput();
  2188.  
  2189.     return;
  2190. }
  2191.  
  2192.  
  2193. //
  2194. // This procedure is invoked to print a large message that may
  2195. // span more than one line. The parameter ptr points to the
  2196. // starting line. The parameter k points to the error message in
  2197. // the error structure.
  2198. //
  2199. void ParseError::PrintLargeMessage(int k)
  2200. {
  2201.     if (control.option.errors)
  2202.     {
  2203.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2204.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2205.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2206.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2207.  
  2208.         if (left_line_no == right_line_no)
  2209.         {
  2210.             Coutput << "\n\n";
  2211.             Coutput.width(6);
  2212.             Coutput << left_line_no << ". ";
  2213.             for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2214.                 Coutput << lex_stream -> InputBuffer()[i];
  2215.  
  2216.             int offset = lex_stream -> WcharOffset(errors[k].left_token, errors[k].right_token);
  2217.             Coutput.width(left_column_no + 8);
  2218.             Coutput << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^" : "<");
  2219.             Coutput.width(right_column_no + errors[k].right_string_length - left_column_no + offset);
  2220.             Coutput.fill('-');
  2221.             Coutput << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2222.             Coutput.fill(' ');
  2223.         }
  2224.         else
  2225.         {
  2226.             Coutput << "\n\n";
  2227.             Coutput.width(left_column_no + 8);
  2228.             Coutput << "<";
  2229.  
  2230.             Coutput.width(lex_stream -> LineSegmentLength(errors[k].left_token));
  2231.             Coutput.fill('-');
  2232.             Coutput << "\n";
  2233.             Coutput.fill(' ');
  2234.  
  2235.             Coutput.width(6);
  2236.             Coutput << left_line_no << ". ";
  2237.             for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  2238.                 Coutput << lex_stream -> InputBuffer()[i];
  2239.  
  2240.             if (right_line_no > left_line_no + 1)
  2241.             {
  2242.                 Coutput.width(left_column_no + 7);
  2243.                 Coutput << " ";
  2244.                 Coutput << ". . .\n";
  2245.             }
  2246.  
  2247.             Coutput.width(6);
  2248.             Coutput << right_line_no << ". ";
  2249.             for (int j = lex_stream -> LineStart(right_line_no); j <= lex_stream -> LineEnd(right_line_no); j++)
  2250.                 Coutput << lex_stream -> InputBuffer()[j];
  2251.  
  2252.             int offset = lex_stream -> WcharOffset(errors[k].right_token);
  2253.             Coutput.width(8);
  2254.             Coutput << "";
  2255.             Coutput.width(right_column_no + errors[k].right_string_length + offset);
  2256.             Coutput.fill('-');
  2257.             Coutput << (errors[k].msg_code == SCOPE_CODE || errors[k].msg_code == MANUAL_CODE ? "^\n" : ">\n");
  2258.             Coutput.fill(' ');
  2259.         }
  2260.     }
  2261.  
  2262.     PrintSecondaryMessage(k);
  2263.  
  2264.     return;
  2265. }
  2266.  
  2267. //
  2268. // This procedure is invoked to form a primary error message. The
  2269. // parameter k identifies the error to be processed.  The global
  2270. // variable: msg, is used to store the message.
  2271. //
  2272. void ParseError::PrintPrimaryMessage(int k)
  2273. {
  2274.     const char *name;
  2275.     int i,
  2276.         len = 0;
  2277.  
  2278. #if defined(FULL_DIAGNOSIS)
  2279.     if (errors[k].name_index >= 0)
  2280.     {
  2281.         len = name_length[errors[k].name_index];
  2282.         name = &string_buffer[name_start[errors[k].name_index]];
  2283.     }
  2284. #endif
  2285.  
  2286.     if (! control.option.errors)
  2287.     {
  2288.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2289.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2290.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2291.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2292.  
  2293.         if (right_column_no != 0) // could not compute a column number
  2294.             right_column_no += (errors[k].right_string_length - 1); // point to last character in right token
  2295.  
  2296.         Coutput << lex_stream -> FileName()
  2297.                 << ':' << left_line_no  << ':' << left_column_no
  2298.                 << ':' << right_line_no << ':' << right_column_no
  2299.                 << ": Syntax: ";
  2300.     }
  2301.     else Coutput << "*** Syntax Error: ";
  2302.  
  2303.     switch(errors[k].msg_code)
  2304.     {
  2305.         case ERROR_CODE:
  2306.              Coutput << "Parsing terminated at this token";
  2307.              break;
  2308.         case BEFORE_CODE:
  2309.              for (i = 0; i < len; i++)
  2310.                  Coutput << name[i];
  2311.              Coutput << " inserted before this token";
  2312.              break;
  2313.         case INSERTION_CODE:
  2314.              for (i = 0; i < len; i++)
  2315.                  Coutput << name[i];
  2316.              Coutput << " expected after this token";
  2317.              break;
  2318.         case DELETION_CODE:
  2319.              if (errors[k].left_token == errors[k].right_token)
  2320.                   Coutput << "Unexpected symbol ignored";
  2321.              else Coutput << "Unexpected symbols ignored";
  2322.              break;
  2323.         case INVALID_CODE:
  2324.              if (len == 0)
  2325.                  Coutput << "Unexpected input discarded";
  2326.              else
  2327.              {
  2328.                  Coutput << "Invalid ";
  2329.                  for (i = 0; i < len; i++)
  2330.                      Coutput << name[i];
  2331.              }
  2332.              break;
  2333.         case SUBSTITUTION_CODE:
  2334.              for (i = 0; i < len; i++)
  2335.                  Coutput << name[i];
  2336.              Coutput << " expected instead of this token";
  2337.              break;
  2338. #if defined(SCOPE_REPAIR)
  2339.         case SCOPE_CODE:
  2340.              Coutput << '\"';
  2341.              for (i = scope_suffix[- (int) errors[k].name_index];
  2342.                   scope_rhs[i] != 0; i++)
  2343.              {
  2344.                  len  = name_length[scope_rhs[i]];
  2345.                  name = &string_buffer[name_start[scope_rhs[i]]];
  2346.                  for (int j = 0; j < len; j++)
  2347.                      Coutput << name[j];
  2348.                  if (scope_rhs[i+1]) // any more symbols to print?
  2349.                      Coutput << ' ';
  2350.              }
  2351.              Coutput << '\"';
  2352.              Coutput << " inserted to complete ";
  2353.              //
  2354.              // TODO: This should not be an option
  2355.              //
  2356.              if (errors[k].scope_name_index)
  2357.              {
  2358.                  len  = name_length[errors[k].scope_name_index];
  2359.                  name = &string_buffer[name_start[errors[k].scope_name_index]];
  2360.                  for (int j = 0; j < len; j++) // any more symbols to print?
  2361.                       Coutput << name[j];
  2362.              }
  2363.              else Coutput << "scope";
  2364.              break;
  2365. #endif
  2366.         case MANUAL_CODE:
  2367.              Coutput << '\"';
  2368.              for (i = 0; i < len; i++)
  2369.                  Coutput << name[i];
  2370.              Coutput << "\" inserted to complete structure";
  2371.              break;
  2372.         case MERGE_CODE:
  2373.              Coutput << "symbols merged to form ";
  2374.              for (i = 0; i < len; i++)
  2375.                  Coutput << name[i];
  2376.              break;
  2377.         case EOF_CODE:
  2378.              for (i = 0; i < len; i++)
  2379.                  Coutput << name[i];
  2380.              Coutput << " reached after this token";
  2381.              break;
  2382.         default:
  2383.              if (errors[k].msg_code == MISPLACED_CODE)
  2384.                   Coutput << "misplaced construct(s)";
  2385.              else if (len == 0)
  2386.                   Coutput << "unexpected input discarded";
  2387.              else
  2388.              {
  2389.                  for (i = 0; i < len; i++)
  2390.                      Coutput << name[i];
  2391.                  Coutput << " expected instead";
  2392.              }
  2393.              break;
  2394.     }
  2395.  
  2396.     Coutput << '\n';
  2397.  
  2398.     return;
  2399. }
  2400.  
  2401. //
  2402. // This procedure is invoked to form a secondary error message.
  2403. // The parameter k identifies the error to be processed.  The
  2404. // global variable: msg, is used to store the message.
  2405. //
  2406. void ParseError::PrintSecondaryMessage(int k)
  2407. {
  2408.     const char *name;
  2409.     int i,
  2410.         len = 0;
  2411.  
  2412. #if defined(FULL_DIAGNOSIS)
  2413.     if (errors[k].name_index >= 0)
  2414.     {
  2415.         len = name_length[errors[k].name_index];
  2416.         name = &string_buffer[name_start[errors[k].name_index]];
  2417.     }
  2418. #endif
  2419.  
  2420.     if (! control.option.errors)
  2421.     {
  2422.         int left_line_no    = lex_stream -> Line(errors[k].left_token),
  2423.             left_column_no  = lex_stream -> Column(errors[k].left_token),
  2424.             right_line_no   = lex_stream -> Line(errors[k].right_token),
  2425.             right_column_no = lex_stream -> Column(errors[k].right_token);
  2426.  
  2427.         if (right_column_no != 0) // could not compute a column number
  2428.             right_column_no += (errors[k].right_string_length - 1); // point to last character in right token
  2429.  
  2430.         Coutput << lex_stream -> FileName()
  2431.                 << ':' << left_line_no  << ':' << left_column_no
  2432.                 << ':' << right_line_no << ':' << right_column_no
  2433.                 << ": Syntax: ";
  2434.     }
  2435.     else Coutput << "*** Syntax Error: ";
  2436.  
  2437.     switch(errors[k].msg_code)
  2438.     {
  2439.         case MISPLACED_CODE:
  2440.             Coutput << "Misplaced construct(s)";
  2441.             break;
  2442. #if defined(SCOPE_REPAIR)
  2443.         case SCOPE_CODE:
  2444.             Coutput << '\"';
  2445.             for (i = scope_suffix[- (int) errors[k].name_index]; scope_rhs[i] != 0; i++)
  2446.             {
  2447.                 len  = name_length[scope_rhs[i]];
  2448.                 name = &string_buffer[name_start[scope_rhs[i]]];
  2449.                 for (int j = 0; j < len; j++) // any more symbols to print?
  2450.                      Coutput << name[j];
  2451.                 if (scope_rhs[i+1])
  2452.                     Coutput << ' ';
  2453.             }
  2454.             Coutput << "\" inserted to complete ";
  2455.             //
  2456.             // TODO: This should not be an option
  2457.             //
  2458.             if (errors[k].scope_name_index)
  2459.             {
  2460.                 len  = name_length[errors[k].scope_name_index];
  2461.                 name = &string_buffer[name_start[errors[k].scope_name_index]];
  2462.                 for (int j = 0; j < len; j++) // any more symbols to print?
  2463.                      Coutput << name[j];
  2464.             }
  2465.             else Coutput << "phrase";
  2466.             break;
  2467. #endif
  2468.         case  MANUAL_CODE:
  2469.             Coutput << '\"';
  2470.             for (i = 0; i < len; i++)
  2471.                 Coutput << name[i];
  2472.             Coutput << "\" inserted to complete structure";
  2473.             break;
  2474.         case MERGE_CODE:
  2475.             Coutput << "Symbols merged to form ";
  2476.             for (i = 0; i < len; i++)
  2477.                 Coutput << name[i];
  2478.             break;
  2479.         default:
  2480.             if (errors[k].msg_code == DELETION_CODE || len == 0)
  2481.                 Coutput << "Unexpected input discarded";
  2482.             else
  2483.             {
  2484.                 for (i = 0; i < len; i++)
  2485.                     Coutput << name[i];
  2486.                 Coutput << " expected instead";
  2487.             }
  2488.     }
  2489.  
  2490.     Coutput << '\n';
  2491.  
  2492.     return;
  2493. }
  2494.